/*
 * Projekt: GMU 2013 - Canny hranovy detektor OpenCL/CUDA
 * Autori: Pavel Nevrala - xnevra00 (xnevra00@stud.fit.vutbr.cz)
 *         Martin Jurak - xjurak02 (xjurak02@stud.fit.vutbr.cz)
 */

#include "ImageCL.h"
#include "GaussianMask.h"
#include "CannyDetectorCL.h"
#include "CannyDetectorCV.h"
#include "ParamController.h"


#include <CL/opencl.h>

/*
 * Hlavni funkce - provede nacteni argumentu programu,
 * jejich kontrolu a spusteni hranoveho detektoru v OpenCL a OpenCV.
 * @argc pocet parametru
 * @argv pole parametru
 * @return navratva hodnota programu
 */

int main(int argc, char* argv[])
{    
	
	ParamController params;

	// parserovani parametru
	try{
		params.parseArgs(argc, argv);
	}
	catch(char* msg){
		cerr << msg << endl;

		cout << "Spusteni:" << endl;
		cout << "canny_detector.exe -in <vstupni obraz> -out <vystupni obraz> [-gDev <std. odchylka pro Gaussuv filtr>] \
			[-gSize <velikost Gaussovy masky>] [-thrL <dolni prah>] [-thrH <horni prah>]" << endl;
		cout << "    -gDev <std. odchylka pro Gaussuv filtr>vychozi odchylka je 1.4" << endl;
		cout << "    -gSize <velikost Gaussovy masky> vychozi velikost je 5" << endl;
		cout << "    -thrL <dolni prah> vychozi dolni prah je 5" << endl;
		cout << "    -thrH <horni prah> vychozi horni prah je 50" << endl;	
		cout << "    -cv soucasne spusti i Cannyho hranovy detektor v OpenCV" << endl;	

		return -1;
	}

	ImageCL inputImage,outputImageCL, outputImageCV;
	GaussianMask gaussianMask;	
	
	// nacteni obrazu a vytvoreni obrazu pro vystup
	try{
		inputImage.loadImage(params.getInImagePath().c_str());
		outputImageCL.loadImage(inputImage.getImageCL(),inputImage.width(),inputImage.height());
		outputImageCV.loadImage(inputImage.getImageCL(),inputImage.width(),inputImage.height());
		gaussianMask.createGaussianMask(params.getGaussMaskSize(),params.getGaussDev());
	}
	catch(char* msg){
		cerr << msg <<endl;
		return -1;
	}

	CannyDetectorCL::device_t device;
	if(params.getDeviceType() == params.CPU)
		device = CannyDetectorCL::CPU;
	else
		device = CannyDetectorCL::GPU;

	// spusteni detekce hran v obraze
	try{
		CannyDetectorCL cannyCL(device);
		cannyCL.detectEdges(inputImage,outputImageCL,gaussianMask,params.getThrLow(),params.getThrHigh());

		if(params.getOpencv() == 1){
			CannyDetectorCV cannyCV;
			cannyCV.detectEdges(inputImage,outputImageCV,gaussianMask,params.getThrLow(),params.getThrHigh());
		}
	}
	catch(...){
		return -1;
	}

	// vypis do souboru
	try{
		outputImageCL.writeImage(params.getOutImagePath().c_str());
		if(params.getOpencv() == 1){
			outputImageCV.writeImage("opencv_canny.jpg");
		}
	}
	catch(char* msg){
		cerr << msg <<endl;
		return -1;
	}

    return 0;
}

